#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time   : 2021/3/27 16:42
# @Author : cjw
"""
爬取步骤：
1、获取主页的页面源代码，知道iframe
2、从iframe的页面源代码中拿到m3u8文件
3、下载第一层m3u8文件 -> 下载第二层m3u8文件(视频存放路径)
4、下载视频分片视频，如果是加密的，需要进行解密操作
5、合并所有ts文件为一个MP4文件
"""
import requests
import re
import aiohttp
import aiofiles
import asyncio
import time
import os
from lxml import etree

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'
}


def get_m3u8_url(url: str):
    """
    获取第二层m3u8的url
    :param url:
    :return:
    """
    # 获取第一m3u8文件下载的url地址
    resp = requests.get(url, headers=headers)
    page_text = resp.text
    obj = re.compile(r'"link_pre":.*?"url":"(?P<url>.*?)",', re.S)
    result = obj.search(page_text)
    # 获取url，并且去除原url中的\符号
    m3u8_first_url = result.group('url').replace('\\', '')
    resp.close()

    # 获取剧集名称
    html = etree.HTML(page_text)
    title_text = html.xpath('//title/text()')[0]
    m3u8_name = title_text.rsplit('_', 1)[0]

    # 获取第一层m3u8请求返回的文件内容
    m3u8_resp = requests.get(m3u8_first_url, headers=headers)
    m3u8_resp.close()
    m3u8_text = m3u8_resp.text

    url_suffix = m3u8_text.split('\n')[-1]  # 分隔获取到第二层m3u8 url的后缀名
    host_url = m3u8_first_url.rsplit('/', 1)[0]  # 截取请求域名
    m3u8_second_url = f'{host_url}/{url_suffix}'

    return m3u8_second_url, m3u8_name


def download_m3u8(url: str, name: str):
    """
    下载分片m3u8文件的内容
    :param url: m3u8下载地址
    :param name: 剧集名称
    :return:
    """
    resp = requests.get(url, headers=headers)
    with open(f'./video/{name}', 'wb') as f:
        f.write(resp.content)
    resp.close()


def get_movie_ts_urls(url: str):
    """
    获取视频分片下载的url列表
    :param url: m3u8下载地址
    :return:
    """
    resp = requests.get(url, headers=headers)
    resp.close()
    result = resp.text
    host = url.rsplit('/', 1)[0]
    urls = [f'{host}/{rs.strip()}' for rs in result.split('\n') if not rs.startswith("#") and rs]
    return urls


async def download_ts(ts_url: str, ts_num: int):
    """
    下载分片ts的文件
    :param ts_url:
    :return:
    """
    async with aiohttp.ClientSession() as session:
        async with session.get(ts_url, headers=headers) as resp:
            content = await resp.content.read()
            async with aiofiles.open(f'./video2/{ts_num}.ts', 'wb') as f:
                await f.write(content)
                print(f'下载完成：{ts_url}')


async def main(urls: list):
    """
    异步下载
    :param urls:
    :return:
    """
    # 任务加载
    tasks = [asyncio.create_task(download_ts(ul, i)) for i, ul in enumerate(urls)]
    await asyncio.wait(tasks)


if __name__ == '__main__':
    index_url = 'https://www.yunbtv.com/vodplay/yueyudiyiji-1-1.html'
    url, name = get_m3u8_url(index_url)
    download_m3u8(url, name)
    url_list = get_movie_ts_urls(url)
    t1 = time.time()
    asyncio.run(main(url_list))
    t2 = time.time()
    print(f'电影下载耗时：{round((t2 - t1), 2)}s')
    # ts_list = [f'./video2/{i}.ts' for i in range(655)]
    # ts_str = '+'.join(ts_list)
    # print(ts_str)
    # os.system(f'copy /b {ts_str} movie.mp4')
